﻿using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using StockUtil;

namespace StockLib.Data.YJ
{
    public class CodeFileLoader : StockLib.Data.CodeFileLoader
    {
        private string GetFinanceFile()
        {
            // HKEY_LOCAL_MACHINE\SOFTWARE\JStockclt InstallPath
            string installDir = string.Empty;
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\JStockclt");
            if (registryKey != null)
            {
                installDir = Convert.ToString(registryKey.GetValue("InstallPath"));
            }
            if (string.IsNullOrEmpty(installDir))
            {
                installDir = @"D:\Program Files\银江网络行情";
            }

            string financeFile = installDir + @"\财务数据.fin";
            return financeFile;
        }

        public override void Load()
        {
            base.Load();

            FileInfo fi = new FileInfo(GetFinanceFile());
            if (!fi.Exists)
                return;

            FileStream fs = null;
            try
            {
                fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
                fs.Seek(Marshal.SizeOf(typeof(FinanceFileHead)), SeekOrigin.Begin);
                byte[] buffer = new byte[Marshal.SizeOf(typeof(FinanceFilePack))];
                while (fs.Read(buffer, 0, buffer.Length) > 0)
                {
                    FinanceFilePack pack = (FinanceFilePack)StructHelper.FromBytes(buffer, typeof(FinanceFilePack));
                    FinanceData finance = new FinanceData();
                    ConvertFinancePackToInternal(ref pack, finance);
                    if (StockContainer.Instance.ContainsKey(finance.CodeKey))
                    {
                        Stock stock = StockContainer.Instance[finance.CodeKey];
                        stock.Finance = finance;
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                throw ex;
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                }
            }
        }

        private void ConvertFinancePackToInternal(ref FinanceFilePack financePack, FinanceData financeData)
        {
            financeData.Market = ConvertMarketToInternal(financePack.m_wMarket);
            financeData.Code = new String(financePack.m_szLabel);
            financeData.ReportDate = Convert.ToInt32(DateTime.Now.ToString("yyyyMMdd"));
            //financeData.ReportType = ReportType.Annals;
            //financeData.ErateDollar = financePack.m_fErateDollar;
            //financeData.ErateHkDollar = financePack.m_fErateHkDollar;

            //financeData.RatioLiquidity = financePack.m_fRatioLiquidity;
            //financeData.RatioQuick = financePack.m_fRatioQuick;
            //financeData.VelocityReceivables = financePack.m_fVelocityReceivables;

            //financeData.VelocityMerchandise = financePack.m_fVelocityMerchandise;
            financeData.MainIncome = financePack.m_fData[21];
            //financeData.CashPs = financePack.m_fCashPs;

            financeData.ProfitMargin = (float)(100 * financePack.m_fData[22] * 1000 / financeData.MainIncome);
            financeData.NetAssetYield = financePack.m_fData[38];

            //financeData.DateBegin = financePack.m_dateBegin;
            financeData.ShareCountTotal = financePack.m_fData[2];
            financeData.ShareCountA = financePack.m_fData[8];
            financeData.ShareCountB = financePack.m_fData[6];
            financeData.ShareCountH = financePack.m_fData[7];
            financeData.ShareCountNational = financePack.m_fData[3];
            financeData.ShareCountCorp = financePack.m_fData[5];
            financeData.ProfitPsud = financePack.m_fData[33];
            financeData.Asset = financePack.m_fData[11] * 1000;
            financeData.RatioHolderRight = financePack.m_fData[37];
            financeData.RatioLongDebt = (float)(100 * financePack.m_fData[17] * 1000 / financeData.Asset);
            financeData.RatioDebt = 100 - financeData.RatioHolderRight;

            financeData.NetAssetPs = financePack.m_fData[35];
            financeData.NetAssetPsRegulate = financePack.m_fData[36];
            financeData.Eps = financePack.m_fData[34];
            financeData.EpsDeduct = (float)(financeData.Eps - financePack.m_fData[25] * 1000 / financeData.ShareCountTotal);
            financeData.NetProfit = financePack.m_fData[31];
            financeData.MainProfit = financePack.m_fData[22];
            financeData.TotalProfit = financePack.m_fData[29];

            //financeData.ProfitInc = financePack.m_fProfitInc;
            //financeData.IncomeInc = financePack.m_fIncomeInc;
            //financeData.AssetInc = financePack.m_fAssetInc;

            //financeData.YieldAverage = financePack.m_fYieldAverage;
            //financeData.YieldStddev = financePack.m_fYieldStddev;
            //financeData.Beite = financePack.m_fBeite;
        }

        private StockMarket ConvertMarketToInternal(UInt16 wMarket)
        {
            const int MARKET_SH = 0X4853;
            const int MARKET_SZ = 0X5A53;

            switch (wMarket)
            {
                case MARKET_SH:
                    return StockMarket.SHSE;

                case MARKET_SZ:
                    return StockMarket.SZSE;
            }

            return StockMarket.Unknown;
        }

        // 分析家格式财务数据
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct FinanceFileHead
        {
            public Int32 m_dwMagic1;	//	0x223FD90C;
            public Int32 m_dwMagic2;	//	0x000000A6;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct FinanceFilePack
        {
            public UInt16 m_wMarket;						                // 市场 'ZS'" 深圳 'HS' 上海
            public UInt16 m_wUnknown;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            public char[] m_szLabel;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 39)]
            public Single[] m_fData;
        }
    }
}
